package com.ebocy.hammer.core.init;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.zip.InflaterInputStream;

import org.apache.log4j.Logger;
import org.dom4j.Attribute;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;

import com.ebocy.hammer.core.GameCache;
import com.ebocy.hammer.core.domain.Block;
import com.ebocy.hammer.core.log.EbocyLogManager;
import com.ebocy.hammer.core.util.Config;
/**
 * 读取flash地图目录下的配置文件，并转为Block对象
 * @author HouQingrong
 * May 25, 2012
 */
public class MapLoader {
	private static Logger logger = EbocyLogManager.getSystemLogger();

	/**
	 * 读取地图配置数据，存入缓存
	 */
	public static void initMapData() {
		GameCache.blockMap = new HashMap<String, List<Block>>();
		List<String> mapNameList = getMapNameList();
		for (String mapName : mapNameList) {
			List<Block> blockList = readBlockDataFromUrl(Config.flashMapConfigUrl + mapName);
//			List<Block> blockList = readBlockDataFromUrl("http://192.168.16.78:8388/hammer/assets/zh/map/data/" + mapName);
			GameCache.blockMap.put(mapName, blockList);
		}
	}

	/**
	 * 读取所有地图的名字
	 */
	private static List<String> getMapNameList() {
		InputStream is = getInputStream(Config.flashConfigUrl);
//		InputStream is = getInputStream("http://192.168.16.78:8388/hammer/assets/zh/gamesetting.xml");
		Document document = null;
		try {
			SAXReader saxReader = new SAXReader();
			document = saxReader.read(is);
		} catch (DocumentException e) {
			e.printStackTrace();
		}

		return extractMapName(document);
	}


	/**
	 * 读取远程zlib文件到InputStream
	 */
	private static List<Block> readBlockDataFromUrl(String fileUrl) {
		List<Block> result = null;
		InputStream is = getInputStream(fileUrl);
		byte[] out = decompress(is);	// 解压zlib文件
		InputStream in = new ByteArrayInputStream(out);	// 读取xml
		SAXReader saxReader = new SAXReader();
		Document document = null;
		try {
			document = saxReader.read(in);
		} catch (DocumentException e) {
			e.printStackTrace();
		}
		result = parseElements2Block(document);
		return result;
	}

	/**
	 * 读取指定url资源到InputStream
	 */
	private static InputStream getInputStream(String fileUrl) {
		InputStream result = null;
		try {
			URL url = new URL(fileUrl);
			URLConnection conn = url.openConnection();
			// 超时设置5秒
			conn.setConnectTimeout(5000);
			conn.setReadTimeout(5000);
			conn.connect();
			result = conn.getInputStream();
			while (result == null) {
				try {
					result = getInputStream(fileUrl);
				} catch (Exception e) {
					logger.debug("读取地图配置文件超时，重试中");
				}
			}
		} catch (MalformedURLException e1) {
			e1.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}

		return result;
	}

	/**
	 * 解压缩zlib文件
	 */
	private static byte[] decompress(InputStream is) {
		InflaterInputStream in = new InflaterInputStream(is);
		ByteArrayOutputStream out = new ByteArrayOutputStream(1024);
		try {
			int i = 1024;
			byte[] buf = new byte[i];
			while ((i = in.read(buf, 0, i)) > 0) {
				out.write(buf, 0, i);
			}
		} catch (IOException e) {
			e.printStackTrace();
		}
		return out.toByteArray();
	}

	/**
	 * 读取block.xml文件并转为Block对象
	 */
	private static List<Block> parseElements2Block(Document document) {
		Iterator<Element> elementIterator = document.getRootElement().elementIterator();
		List<Block> blocks = new ArrayList<Block>();
		while (elementIterator.hasNext()) {
			Element elementItem = elementIterator.next();
			if (elementItem.getName().equals("blocks")) {
				Iterator<Element> blocksSubElementIterator = elementItem.elementIterator();
				while (blocksSubElementIterator.hasNext()) {
					Element blocksSubElement = blocksSubElementIterator.next();
					if (blocksSubElement.getName().equals("block")) {
						Block block = new Block();
						Iterator<Attribute> attributeIterator = blocksSubElement.attributeIterator();
						while (attributeIterator.hasNext()) {
							Attribute attributeItem = attributeIterator.next();
							if (attributeItem.getName().equals("row")) {
								block.setRow(Short.parseShort(attributeItem.getValue()));
							}
							if (attributeItem.getName().equals("column")) {
								block.setCol(Short.parseShort(attributeItem.getValue()));
							}
						}

						Iterator<Element> blockSubElementIterator = blocksSubElement.elementIterator();
						while (blockSubElementIterator.hasNext()) {
							Element blockSubElement = blockSubElementIterator.next();
							if (blockSubElement.getName().equals("propertys")) {
								Iterator<Element> propertiesIterator = blockSubElement.elementIterator();
								while (propertiesIterator.hasNext()) {
									Element property = propertiesIterator.next();
									if (property.getName().equals("durability"))
										block.setDurability(Short.parseShort(property.getTextTrim()));
									if (property.getName().equals("recoverTime"))
										block.setRecoverTime(Short.parseShort(property.getTextTrim()));
								}
							}
						}

						blocks.add(block);
					}
				}
			}
		}
		return blocks;
	}

	/**
	 * 读取gameSetting.xml中地图名配置数据
	 */
	private static List<String> extractMapName(Document document) {
		List<String> mapNameList = new ArrayList<String>();
		Iterator<Element> elementIterator = document.getRootElement().elementIterator();
		while (elementIterator.hasNext()) {
			Element element  = elementIterator.next();
			if (element.getName().equals("extend")) {
				Iterator<Element> subElementIterator = element.elementIterator();
				while (subElementIterator.hasNext()) {
					Element subElement = subElementIterator.next();
					if (subElement.getName().equals("maps")) {
						Iterator<Element> thirdElementIterator = subElement.elementIterator();
						while (thirdElementIterator.hasNext()) {
							Element thirdElement = thirdElementIterator.next();
							if (thirdElement.getName().equals("map")) {
								mapNameList.add(thirdElement.attribute("name").getValue());
							}
						}
					}
					break;
				}
			}
		}
		return mapNameList;
	}
}
